#pragma once
#include "Matrix.h"
#include <iostream>
#include <map>

const extern int Nb;
extern Matrix<uint8_t> MIX_Matrix;
extern Matrix<uint8_t> INV_MIX_Matrix;
extern Matrix<uint8_t> S_BOX;
extern Matrix<uint8_t> INV_S_BOX;
extern std::map<uint32_t, uint32_t> RocnBuffer;
 
Matrix<uint8_t>* ConvertBitsToMatrix(const std::vector<uint8_t> bits);
uint8_t Multiply2InGF256(const  uint8_t origin);
uint8_t Multiply(const uint8_t param1,const uint8_t pararm2);
uint32_t SubWord(uint32_t word);
uint32_t RotWord(uint32_t word);
uint32_t Rocn( uint32_t&& word);
uint32_t Rocn(const uint32_t& word);
std::vector<uint32_t>* KeyExpansion(const::std::vector< uint8_t> key);
void SubBytes(Matrix<uint8_t>& state);
void InvSubBytes(Matrix<uint8_t>& state);
void ShiftRows(Matrix<uint8_t>& state);
void InvShiftRows(Matrix<uint8_t>& state);
void MixColumns(Matrix<uint8_t>& state);
void InvMixColumns(Matrix<uint8_t>& state);
void AddRoundKey(Matrix<uint8_t>& state, const uint32_t* roundKey);
std::vector<uint8_t>* Encrypt(const::std::vector<uint8_t> textCodes, const std::vector<uint8_t>& keyCodes);
std::vector<uint8_t>* Decrypt(const::std::vector<uint8_t> textCodes, const std::vector<uint8_t>& keyCodes);
std::vector<uint8_t>* Encrypt(const::std::vector<uint8_t> textCodes, const std::vector<uint32_t>& expandedKey);
std::vector<uint8_t>* Decrypt(const::std::vector<uint8_t> textCodes, const std::vector<uint32_t>& expandedKey);

std::vector<uint8_t>* DecryptText(const std::string decrypedText, const std::string key);

std::vector<uint8_t>* ConvertTextToCodes(const std::string plainText);
std::stringbuf* EncryptText(const std::string plainText, const std::string key);
